package com.sunwayworld.basemodule.business.pjreport.service.impl;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.sunwayworld.basemodule.business.batch.bean.LimsBatchBean;
import com.sunwayworld.basemodule.business.batch.bean.LimsBatchSampleBean;
import com.sunwayworld.basemodule.business.pjreport.bean.LimsPjReportBean;
import com.sunwayworld.basemodule.business.pjreport.dao.LimsPjReportDao;
import com.sunwayworld.basemodule.business.pjreport.service.LimsPjReportService;
import com.sunwayworld.basemodule.common.utils.AsposeWordUtils;
import com.sunwayworld.basemodule.rm.client.bean.LimsClientBean;
import com.sunwayworld.basemodule.rm.client.service.LimsClientService;
import com.sunwayworld.cloud.lims.reporttemplate.bean.LimsReportTemplateBean;
import com.sunwayworld.cloud.lims.reporttemplate.service.LimsReportTemplateService;
import com.sunwayworld.cloud.lims.reporttemplate.support.util.LimsFileUtils;
import com.sunwayworld.cloud.lims.reporttemplate.support.word.LimsWordReportGenerator;
import com.sunwayworld.cloud.module.lcdp.base.service.LcdpBaseService;
import com.sunwayworld.framework.at.annotation.AuditTrailEntry;
import com.sunwayworld.framework.at.annotation.AuditTrailType;
import com.sunwayworld.framework.audit.aunnotation.Audit;
import com.sunwayworld.framework.context.ApplicationContextHelper;
import com.sunwayworld.framework.context.LocalContextHelper;
import com.sunwayworld.framework.database.sql.Order;
import com.sunwayworld.framework.exception.InvalidDataException;
import com.sunwayworld.framework.i18n.I18nHelper;
import com.sunwayworld.framework.io.file.FilePathDTO;
import com.sunwayworld.framework.io.file.FilePathManager;
import com.sunwayworld.framework.io.file.FileScope;
import com.sunwayworld.framework.mybatis.mapper.MapperParameter;
import com.sunwayworld.framework.mybatis.mapper.MatchPattern;
import com.sunwayworld.framework.mybatis.mapper.SearchFilter;
import com.sunwayworld.framework.restful.data.RestJsonWrapperBean;
import com.sunwayworld.framework.spring.annotation.GikamBean;
import com.sunwayworld.framework.support.auditable.bean.CoreBpmnParameterDTO;
import com.sunwayworld.framework.utils.*;
import com.sunwayworld.framework.utils.StringUtils;
import com.sunwayworld.module.item.file.bean.CoreFileBean;
import com.sunwayworld.module.item.file.manager.CoreFileManager;
import com.sunwayworld.module.item.file.service.CoreFileService;
import com.sunwayworld.module.item.file.utils.CoreFileUtils;
import com.sunwayworld.module.sys.bpmn.bean.CoreBpmnInstanceStatusDTO;
import com.sunwayworld.module.sys.bpmn.engine.CoreBpmnRuntimeService;
import com.sunwayworld.module.sys.bpmn.engine.CoreBpmnRuntimeSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

@Repository
@GikamBean
public class LimsPjReportServiceImpl implements LimsPjReportService {

    @Autowired
    private LimsPjReportDao limsPjReportDao;

    @Override
    @SuppressWarnings("unchecked")
    public LimsPjReportDao getDao() {
        return limsPjReportDao;
    }

    @Autowired
    private LimsReportTemplateService reportTemplateService;

    @Autowired
    @Lazy
    private CoreFileService coreFileService;

    @Autowired
    @Lazy
    private CoreFileManager fileManager;

    @Autowired
    @Lazy
    private LimsClientService clientService;

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.INSERT)
    public Long insert(RestJsonWrapperBean jsonWrapper) {
        LimsPjReportBean limsPjReport = jsonWrapper.parseUnique(LimsPjReportBean.class);
        limsPjReport.setId(ApplicationContextHelper.getNextIdentity());
        getDao().insert(limsPjReport);
        return limsPjReport.getId();
    }

    @Override
    @Transactional
    public void createReports(String ids) {
        List<Long> reportIds = Arrays.stream(ids.split(",")).map(NumberUtils::parseLong).collect(Collectors.toList());
        List<LimsPjReportBean> reportBeans = selectListByFilter(SearchFilter.instance()
                .match("id", reportIds).filter(MatchPattern.OR)
                .match("processStatus", "draft").filter(MatchPattern.SB));
        Optional<LimsPjReportBean> first = reportBeans.stream().filter(r -> r.getReportTemplateId() == null).findFirst();
        if (first.isPresent()) throw new InvalidDataException(I18nHelper.getMessage("NO.ADAPTER.ANY.REPORT.TEMPLATE"));
//        createReport(reportBeans, false);
        // 这里不清楚具体要咋设计的，报告只有编制页可以生成，这里把approve改成true，可以在生成时放置用户
        createReport(reportBeans, false);
    }

    private void createReport(List<LimsPjReportBean> reportBeans, boolean approve) {
        if (CollectionUtils.isEmpty(reportBeans)) return;

        MapperParameter parameter = new MapperParameter();
        for (LimsPjReportBean reportBean : reportBeans) {
            parameter.clear();
            parameter.put("reportNo", reportBean.getReportNo()); // 传参数，报告编号
            parameter.put("generatorId", approve ? reportBean.getGeneratorId() : LocalContextHelper.getLoginUserId());
            parameter.put("userId", approve ? LocalContextHelper.getLoginUserId() : "1");
            LimsReportTemplateBean limsWordTemplateBean = reportTemplateService.selectById(reportBean.getReportTemplateId());
            if (limsWordTemplateBean == null) {
                throw new InvalidDataException(I18nHelper.getMessage("NO.ADAPTER.ANY.REPORT.TEMPLATE"));
            }
            LimsWordReportGenerator wordWordGenerator = new LimsWordReportGenerator(limsWordTemplateBean, parameter);
            FilePathDTO templateFile = wordWordGenerator.buildReport();

            String fileName = reportBean.getExt$Item("sampleName") + " " + reportBean.getSampleCodes() + ".pdf";
            FilePathDTO pdfFile = FilePathDTO.of(FileScope.temp.name(), templateFile.getTimestamp(), templateFile.getIrregularName()
                    , fileName + ".pdf");

            Path localPath = FilePathManager.getLocalPath(templateFile);
            AsposeWordUtils.doc2pdf(localPath.toString(), FilePathManager.getLocalPath(pdfFile).toString());
            FileUtils.deleteQuietly(localPath.toFile());

            // 保存文件
            String targetId = getDao().getTable() + "$" + reportBean.getId();
            List<CoreFileBean> coreFileBeans = coreFileService.selectFileListByTargetIds(targetId);
            coreFileBeans.forEach(f -> f.setBizCategory("history"));
            // 更新为 历史报告
            coreFileService.getDao().update(coreFileBeans, "bizCategory");
            CoreFileBean coreFileBean = new CoreFileBean();
            coreFileBean.setTargetId(targetId);
            coreFileBean.setBizCategory("audit");
            coreFileBean.setVersion((long) coreFileBeans.size());
            Long uploadKey = coreFileService.upload(coreFileBean, FilePathManager.getLocalPath(pdfFile));

            reportBean.setReportFileName(fileName);
            reportBean.setReportFileId(uploadKey);
            if (!approve) {
                reportBean.setGenerator(LocalContextHelper.getLoginUserName());
                reportBean.setGeneratorId(LocalContextHelper.getLoginUserId());
            }
        }
        getDao().fastUpdate(reportBeans, "reportFileName", "reportFileId", "generator", "generatorId");
    }

    @Override
    public void approveCallback(List<Long> idList) {
        if (idList.isEmpty()) {
            return;
        }
        List<LimsPjReportBean> beans = this.selectListByIds(idList);
        if (beans.isEmpty()) {
            return;
        }
        LocalDateTime now = LocalDateTime.now();
        beans.forEach(b -> {
            b.setSigner(LocalContextHelper.getLoginUserName());
            b.setSignerId(LocalContextHelper.getLoginUserId());
            b.setAuditTime(now);
        });
        getDao().update(beans, "auditTime", "signer", "signerId");
    }

    @Override
    public void previewReport(String ids, HttpServletResponse response) {
        List<Long> reportIds = Arrays.stream(ids.split(",")).map(NumberUtils::parseLong).collect(Collectors.toList());
        List<LimsPjReportBean> reportBeans = getDao().selectListByIds(reportIds);
        if (reportBeans.isEmpty()) {
            throw new InvalidDataException(I18nHelper.getMessage("T_LIMS_REPORT.REPORTFILE_NOT_FOUND"));
        }
        Optional<LimsPjReportBean> any = reportBeans.stream().filter(r -> !ObjectUtils.isEmpty(r.getReportFileId())).findAny();
        if (!any.isPresent()) {
            throw new InvalidDataException(I18nHelper.getMessage("T_LIMS_REPORT.REPORTFILE_NOT_FOUND"));
        }
        List<FilePathDTO> outFileList = new ArrayList<>();
        List<Long> fileIdList = reportBeans.stream().filter(r -> !ObjectUtils.isEmpty(r.getReportFileId())).map(LimsPjReportBean::getReportFileId).collect(Collectors.toList());
        //List<CoreFileBean> fileBeans = coreFileService.selectFileListByTargetIds(reportIds.stream().map(id -> getDao().getTable() + "$" + id).toArray(String[]::new));
        List<CoreFileBean> fileBeans = coreFileService.selectListByIds(fileIdList);
        List<CoreFileBean> pdfFile = fileBeans.stream().filter(fileBean -> fileBean.getFileExt().equalsIgnoreCase("pdf")).collect(Collectors.toList());
        Optional<CoreFileBean> optionalCoreFileBean = fileBeans.stream().filter(f -> ArrayUtils.asList("doc", "docx").contains(f.getFileExt().toLowerCase())).findFirst();
        if (optionalCoreFileBean.isPresent()) {
            List<CoreFileBean> coreFileBeanList = fileBeans.stream().filter(f -> ArrayUtils.asList("doc", "docx").contains(f.getFileExt().toLowerCase())).collect(Collectors.toList());
            coreFileBeanList.parallelStream().forEach(p -> {
                FilePathDTO tempPdfFile = FilePathDTO.of(FileScope.temp.name(), "" + System.currentTimeMillis(), UUID.randomUUID().toString(), ".pdf");
                FilePathDTO tempWordFile = FilePathDTO.of(FileScope.temp.name(), "" + System.currentTimeMillis(), UUID.randomUUID().toString(), ".docx");
                Path copyDirPath = FilePathManager.getLocalDirPath(tempWordFile);
                Path absolutePath = FilePathManager.getLocalPath(tempWordFile);
                try {
                    Files.createDirectories(copyDirPath);
                    FilePathDTO filePathDTO = CoreFileUtils.toFilePath(p);
                    Path path = LimsFileUtils.getFilePath(p);
                    File file = path.toFile();
                    if (file.exists()) {
                        Files.copy(FilePathManager.getLocalPath(filePathDTO), FilePathManager.getLocalPath(tempWordFile));
                        AsposeWordUtils.doc2pdf(absolutePath.toString(), FilePathManager.getLocalPath(tempPdfFile).toString());
                        outFileList.add(tempPdfFile);
                    }
                } catch (IOException e) {
                    throw new InvalidDataException("create directory failed！");
                }
            });
        }
        FilePathDTO outFile = FilePathDTO.of(FileScope.temp.name(), "" + System.currentTimeMillis(), UUID.randomUUID().toString(),
                DateTimeUtils.formatLocalDate(LocalDate.now()) + "-" + "报告预览.pdf");
        if (!pdfFile.isEmpty()) {
            pdfFile.forEach(r -> outFileList.add(CoreFileUtils.toFilePath(r)));
        }
        if (outFileList.isEmpty()) {
            throw new InvalidDataException("not found report file!");
        }
        coreFileService.mergePdfList(outFileList, outFile);
        FileInputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(FilePathManager.getLocalPath(outFile).toFile());
            response.setContentType("application/pdf");
            out = response.getOutputStream();
            byte[] b = new byte[4 * 1024];
            while ((in.read(b)) != -1) {
                out.write(b);
            }
            out.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public String downloadReports(String ids, HttpServletResponse response) {
        List<Long> reportIds = Arrays.stream(ids.split(",")).map(NumberUtils::parseLong).collect(Collectors.toList());
        List<LimsPjReportBean> reportBeans = selectListByIds(reportIds);
        if (CollectionUtils.isEmpty(reportBeans)) {
            throw new InvalidDataException("request parameter error!");
        }
        //过滤未上传附件报告
        Optional<LimsPjReportBean> first = reportBeans.stream().filter(r -> ObjectUtils.isEmpty(r.getReportFileName())).findFirst();
        if (first.isPresent()) {
            StringBuilder sb = new StringBuilder();
            sb.append("the following reports：").append("</br>");
            List<LimsPjReportBean> beans = reportBeans.stream().filter(r -> ObjectUtils.isEmpty(r.getReportFileName())).collect(Collectors.toList());
            beans.forEach(b -> {
                sb.append(b.getReportNo()).append("<br/>");
            });
            sb.append("not found report and download failed !");
            throw new InvalidDataException(sb.toString());
        }
        //当前报告附件
        List<Long> fileIdList = reportBeans.stream().map(LimsPjReportBean::getReportFileId).collect(Collectors.toList());
        List<CoreFileBean> fileBeans = coreFileService.selectFileListByTargetIds(reportIds.stream().map(s -> getDao().getTable() + "$" + s).toArray(String[]::new));
        if (fileBeans.isEmpty()) {
            throw new InvalidDataException("Not Found Report!");
        }
        Optional<CoreFileBean> optionalCoreFileBean = fileBeans.stream().filter(f -> fileIdList.contains(f.getId())).findFirst();
        if (!optionalCoreFileBean.isPresent()) {
            throw new InvalidDataException("Not Found Report!");
        }
        List<CoreFileBean> targetFileList = fileBeans.stream().filter(g -> fileIdList.contains(g.getId())).collect(Collectors.toList());
        List<CoreFileBean> atts = coreFileService.selectFileListByTargetIds(reportIds.stream().map(s -> "T_LIMS_PJ_REPORT$" + s).toArray(String[]::new)); // 报告附件
        FilePathDTO filePathDTO = FilePathDTO.of(FileScope.temp.name(), LocalDateTime.now(), StringUtils.randomUUID(16), DateTimeUtils.formatLocalDate(LocalDate.now()) + "-" + I18nHelper.getMessage("GIKAM.REPORT.PACK.DOWNLOAD_FILE_NAME") + ".zip");
        Path localDirPath = FilePathManager.getLocalDirPath(filePathDTO);
        Set<Path> zipPathSet = new HashSet<>();
        try {
            Files.createDirectories(localDirPath);
            for (LimsPjReportBean reportBean : reportBeans) {
                CoreFileBean reportFile = targetFileList.stream().filter(f -> f.getTargetId().contains(reportBean.getId().toString())).findFirst().get(); // 报告文件
                List<CoreFileBean> attFiles = atts.stream().filter(f -> f.getTargetId().contains(reportBean.getId().toString())).collect(Collectors.toList());  // 报告附件
                Path path = LimsFileUtils.getFilePath(reportFile);
                File file = path.toFile();
                if (file.exists()) {
                    zipPathSet.add(path);
                }
                if (!CollectionUtils.isEmpty(attFiles)) {
                    for (CoreFileBean attFile : attFiles) {
                        File attf = LimsFileUtils.getFilePath(attFile).toFile();
                        if (attf.exists()) {
                            zipPathSet.add(attf.toPath());
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (!zipPathSet.isEmpty()) {
            ArchiveUtils.zip(FilePathManager.getLocalPath(filePathDTO), zipPathSet.toArray(new Path[zipPathSet.size() - 1]));
            fileManager.upload(filePathDTO, FilePathManager.getLocalPath(filePathDTO));
            zipPathSet.forEach(FileUtils::deleteRecursively);
            return FilePathManager.getUrl(filePathDTO);
        } else {
            return "-1";
        }
    }

    @Transactional
    @AuditTrailEntry(AuditTrailType.PROCESS_COMPLETE)
    @Audit("AUDIT.PROCESS_COMPLETE")
    public List<CoreBpmnInstanceStatusDTO<Long>> completeTask(RestJsonWrapperBean wrapper) {
        List<LimsPjReportBean> itemList = wrapper.parse(this.getDao().getType());
        if (itemList.isEmpty()) {
            return CollectionUtils.emptyList();
        } else {
            this.checkAndUpdateVersion(itemList);
            CoreBpmnRuntimeService runtimeService = ApplicationContextHelper.getBean(CoreBpmnRuntimeService.class);
            List<Long> itemIdList = itemList.stream().map(LimsPjReportBean::getId).collect(Collectors.toList());
            List<LimsPjReportBean> selectItemList = this.getBpmnVarsItemList(itemIdList);

            createReport(selectItemList, true);

            List<CoreBpmnRuntimeSource<LimsPjReportBean, Long>> runtimeSourceList = this.parseAuditableRuntimeSource(itemIdList, CoreBpmnParameterDTO.of(wrapper), this.getBpmnVars(wrapper, selectItemList));
            List<CoreBpmnInstanceStatusDTO<Long>> instanceStatusList = runtimeService.completeTask(runtimeSourceList);
            this.autoPass(runtimeSourceList, instanceStatusList);
            return instanceStatusList;
        }
    }

    @Transactional
    @AuditTrailEntry(AuditTrailType.PROCESS_REJECT)
    @Audit("AUDIT.PROCESS_REJECT")
    public List<CoreBpmnInstanceStatusDTO<Long>> rejectTask(RestJsonWrapperBean wrapper) {
        List<LimsPjReportBean> itemList = wrapper.parse(this.getDao().getType());
        if (itemList.isEmpty()) {
            return CollectionUtils.emptyList();
        } else {
            this.checkAndUpdateVersion(itemList);
            CoreBpmnRuntimeService runtimeService = ApplicationContextHelper.getBean(CoreBpmnRuntimeService.class);
            List<Long> itemIdList = itemList.stream().map(LimsPjReportBean::getId).collect(Collectors.toList());
            List<LimsPjReportBean> selectItemList = this.getBpmnVarsItemList(itemIdList);

            List<Long> fileIds = selectItemList.stream().map(LimsPjReportBean::getReportFileId).filter(Objects::nonNull).collect(Collectors.toList());
            CoreFileBean updateBy = new CoreFileBean();
            updateBy.setBizCategory("history");
            coreFileService.getDao().updateByIds(updateBy, fileIds, "bizCategory");

            List<CoreBpmnRuntimeSource<LimsPjReportBean, Long>> runtimeSourceList = this.parseAuditableRuntimeSource(itemIdList, CoreBpmnParameterDTO.of(wrapper), this.getBpmnVars(wrapper, selectItemList));
            return runtimeService.rejectTask(runtimeSourceList);
        }
    }

    @Transactional
    @AuditTrailEntry(AuditTrailType.PROCESS_UNDO)
    @Audit("AUDIT.PROCESS_UNDO")
    public List<CoreBpmnInstanceStatusDTO<Long>> undo(RestJsonWrapperBean wrapper) {
        List<LimsPjReportBean> itemList = wrapper.parse(this.getDao().getType());
        if (itemList.isEmpty()) {
            return CollectionUtils.emptyList();
        } else {
            this.checkAndUpdateVersion(itemList);
            CoreBpmnRuntimeService runtimeService = ApplicationContextHelper.getBean(CoreBpmnRuntimeService.class);
            List<Long> itemIdList = itemList.stream().map(LimsPjReportBean::getId).collect(Collectors.toList());
            List<LimsPjReportBean> selectItemList = this.getBpmnVarsItemList(itemIdList);

            List<Long> fileIds = selectItemList.stream().map(LimsPjReportBean::getReportFileId).filter(Objects::nonNull).collect(Collectors.toList());
            CoreFileBean updateBy = new CoreFileBean();
            updateBy.setBizCategory("history");
            coreFileService.getDao().updateByIds(updateBy, fileIds, "bizCategory");

            List<CoreBpmnRuntimeSource<LimsPjReportBean, Long>> runtimeSourceList = this.parseUndoableRuntimeSource(itemIdList, CoreBpmnParameterDTO.of(wrapper), this.getBpmnVars(wrapper, selectItemList));
            return runtimeService.undo(runtimeSourceList);
        }
    }

    @Override
    public String reportsGroupMergeDownload(String ids, String type, HttpServletResponse response) {
        List<Long> reportIds = Arrays.stream(ids.split(",")).map(NumberUtils::parseLong).collect(Collectors.toList());
        List<LimsPjReportBean> reportBeans = this.selectListByFilter(SearchFilter.instance().match("id", reportIds).filter(MatchPattern.OR)
                , Order.desc("SAMPLENAME"));

        if (CollectionUtils.isEmpty(reportBeans)) {
            throw new InvalidDataException("request parameter error!");
        }

//        List<String> customerNames = reportBeans.stream().map(p -> p.getExt$Item("customername")).distinct().collect(Collectors.toList());
//        List<LimsClientBean> clientBeans = clientService.selectListByFilter(SearchFilter.instance().match("clientName", customerNames).filter(MatchPattern.OR));

        //过滤未上传附件报告
        Optional<LimsPjReportBean> first = reportBeans.stream().filter(r -> "0".equals(r.getExt$Item("GENERATEREPORTFLAG"))).findFirst();
        if (first.isPresent()) {
            StringBuilder sb = new StringBuilder();
            sb.append("the following reports：").append("</br>");
            List<LimsPjReportBean> beans = reportBeans.stream().filter(r -> "0".equals(r.getExt$Item("GENERATEREPORTFLAG"))).collect(Collectors.toList());
            beans.forEach(b -> {
                sb.append(b.getReportNo()).append("<br/>");
            });
            sb.append("not found report and download failed !");
            throw new InvalidDataException(sb.toString());
        }
        //当前报告附件
        List<Long> fileIdList = reportBeans.stream().map(LimsPjReportBean::getReportFileId).collect(Collectors.toList());
        List<CoreFileBean> fileBeans = coreFileService.selectFileListByTargetIds(reportIds.stream().map(s -> getDao().getTable() + "$" + s).toArray(String[]::new));
        if (fileBeans.isEmpty()) {
            throw new InvalidDataException("Not Found Report!");
        }
        Optional<CoreFileBean> optionalCoreFileBean = fileBeans.stream().filter(f -> fileIdList.contains(f.getId())).findFirst();
        if (!optionalCoreFileBean.isPresent()) {
            throw new InvalidDataException("Not Found Report!");
        }
        List<CoreFileBean> targetFileList = fileBeans.stream().filter(g -> fileIdList.contains(g.getId())).collect(Collectors.toList());
        targetFileList.forEach(f -> fileManager.download(f));
//        if (reportBeans.size() == 1) {
//            if ("XG".equalsIgnoreCase(reportBeans.get(0).getReportCategory()) && "阴性".equalsIgnoreCase(reportBeans.get(0).getReportResult())) {
//            } else {
//                CoreFileBean reportFile = targetFileList.stream().filter(f -> f.getTargetId().contains(reportBeans.get(0).getId().toString())).findFirst().get(); // 报告文件
//                FilePathDTO filePathDTO = CoreFileUtils.toFilePath(reportFile);
//                return FilePathManager.getUrl(filePathDTO);
//            }
//        }
        List<FilePathDTO> resultPdfs = new ArrayList<>();
        try {
            Map<String, List<LimsPjReportBean>> mergeGroup = reportBeans.stream().collect(Collectors.groupingBy(r -> r.getExt$Item("samplename")));
            for (String s : mergeGroup.keySet()) {
                List<LimsPjReportBean> reports = mergeGroup.get(s);

                if (!reports.isEmpty()) {
                    //重新查询排序
//                    List<LimsPjReportBean> reportBeanList = this.selectListByFilter(SearchFilter.instance().match("id", reports.stream().map(LimsPjReportBean::getId).collect(Collectors.toList())).filter(MatchPattern.OR)
//                            , Order.desc("ID"));
//                    List<Long> reportFileIds = reportBeanList.stream().map(LimsPjReportBean::getReportFileId).filter(Objects::nonNull).collect(Collectors.toList());
                    //List<CoreFileBean> reportFiles = targetFileList.stream().filter(f -> reportFileIds.contains(f.getId())).collect(Collectors.toList());
                    //List<CoreFileBean> reportFiles =coreFileService.selectListByFilter(SearchFilter.instance().match("id",reportFileIds ).filter(MatchPattern.OR));
                    MapperParameter temp = new MapperParameter();
                    temp.clear();
                    temp.setFilter(SearchFilter.instance().match("reportId", reports.stream().map(LimsPjReportBean::getId).collect(Collectors.toList())).filter(MatchPattern.OR));
                    List<CoreFileBean> reportFiles = getDao().selectFileByCondition(temp);
                    if (!reportFiles.isEmpty()) {

                        //过滤客户名称相同的
//                        LimsClientBean clientBean = clientBeans.stream().filter(c -> reports.get(0).getExt$Item("customername").equals(c.getClientName())).collect(Collectors.toList()).get(0);
//                        List<FilePathDTO> source = reportFiles.stream().map(CoreFileUtils::toFilePath).collect(Collectors.toList());
                        //报告合并名称
//                        String combinedReportName = clientBean.getCombinedReportName();
                        String name = s;
                        name = DateTimeUtils.formatLocalDate(LocalDate.now(), "YYYY-MM-dd") + "-" + name;
//                        if (combinedReportName != null && combinedReportName.equals("YYYY-MM-DD-NAME")) {
//                            name = DateTimeUtils.formatLocalDate(LocalDate.now(), "YYYY-MM-dd") + "-" + name;
//                        }
//                        if (combinedReportName != null && combinedReportName.equals("NAME ID")) {
//                            LimsBatchSampleBean bean = limsBatchSampleService.selectFirstByFilter(
//                                    SearchFilter.instance().match("batchId", reports.get(0).getBatchId()).filter(MatchPattern.EQ));
//                            name = name + " " + bean.getGeneralImportId();
//                        }
//                        if (combinedReportName != null && combinedReportName.equals("NAME Lab Number")) {
//                            LimsBatchBean batchBean = limsBatchService.getDao().selectById(reports.get(0).getBatchId());
//                            name = name + " " + batchBean.getIdentifyCode();
//                        }
                        FilePathDTO filePathDTO = FilePathDTO.of(FileScope.temp.name(), LocalDateTime.now(), StringUtils.randomUUID(16), name + ".pdf");
                        Path localDirPath = FilePathManager.getLocalDirPath(filePathDTO);
                        Files.createDirectories(localDirPath);
//                        coreFileService.mergePdfList(source, filePathDTO);
//                        PdfUtils.mergePdfFiles(FilePathManager.getLocalPath(filePathDTO), pdfList.toArray(new Path[0]));
                        //PdfUtils.mergePdfFiles(FilePathManager.getLocalPath(filePathDTO), reportFiles.stream().map(LimsFileUtils::getFilePath).toArray(Path[]::new));

                        List<File> files = new ArrayList<>();
                        reportFiles.forEach(p -> {
                            FilePathDTO filePath1 = CoreFileUtils.toFilePath(p);
                            Path path = FilePathManager.getLocalPath(filePath1);
                            File file = path.toFile();
                            files.add(file);
                        });

                        mergePdfFiles(files, FilePathManager.getLocalPath(filePathDTO).toString());
                        resultPdfs.add(filePathDTO);
                        fileManager.upload(filePathDTO, FilePathManager.getLocalPath(filePathDTO));
                    } else {

                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (!resultPdfs.isEmpty()) {
//            String urls = resultPdfs.stream().map(path -> fileManager.getDownloadUrl(path)).collect(Collectors.joining(","));

            FilePathDTO filePathDTO = FilePathDTO.of(FileScope.temp.name(), LocalDateTime.now(), StringUtils.randomUUID(16), DateTimeUtils.formatLocalDate(LocalDate.now()) + "-" + I18nHelper.getMessage("GIKAM.REPORT.PACK.DOWNLOAD_FILE_NAME") + ".zip");
            Set<Path> zipPathSet = new HashSet<>();
            resultPdfs.forEach(f -> {
                zipPathSet.add(FilePathManager.getLocalPath(f));
            });
            ArchiveUtils.zip(FilePathManager.getLocalPath(filePathDTO), zipPathSet.toArray(new Path[zipPathSet.size() - 1]));
            fileManager.upload(filePathDTO, FilePathManager.getLocalPath(filePathDTO));
            zipPathSet.forEach(FileUtils::deleteRecursively);
            return FilePathManager.getUrl(filePathDTO);
//            return urls;
        } else {
            return "-1";
        }
    }

    //合并pdf文件
    public void mergePdfFiles(List<File> files, String newfile) {
        boolean retValue = false;
        Document document = null;
        try {
            document = new Document(new PdfReader(files.get(0).toString()).getPageSize(1));
            PdfCopy copy = new PdfCopy(document, new FileOutputStream(newfile));
            document.open();
            int pagesNum = 0;//总页码
            int pages = 0;//当前页码
            for (int i = 0; i < files.size(); i++) {
                PdfReader reader = new PdfReader(files.get(i).toString());
                pagesNum += reader.getNumberOfPages();
            }
            for (int i = 0; i < files.size(); i++) {
                PdfReader reader = new PdfReader(files.get(i).toString());
                PdfCopy.PageStamp stamp;//插入页码所需  不要页码可删除
                int n = reader.getNumberOfPages();
                for (int j = 1; j <= n; j++) {
                    pages++;
                    document.newPage();
                    PdfImportedPage page = copy.getImportedPage(reader, j);
                    stamp = copy.createPageStamp(page);//插入页码所需  不要页码可删除
                    String patten = "Page %d of %d";
//                    if("1".equalsIgnoreCase(ruleConfig.getExt$Item("flag"))) {
                    patten = "%d / %d";
//                    }
                    float x = 300f;
                    float y = 16f;
//                    if("1".equalsIgnoreCase(weiz.getExt$Item("flag")) && weiz.getParamVal() != null) {
//                        String[] split = ruleConfig.getParamVal().split(",");
//                        if(split.length > 1) {
//                            x = Float.parseFloat(split[0]);
//                            y = Float.parseFloat(split[1]);
//                        }
//                    }
                    ColumnText.showTextAligned(stamp.getUnderContent(), Element.ALIGN_CENTER, new Phrase(addFont(String.format(patten, pages, pagesNum))), x, y, 0f);//插入页码所需  不要页码可删除
                    stamp.alterContents();//插入页码所需  不要页码可删除
                    copy.addPage(page);
                }
                reader.close();
            }
            copy.close();
        } catch (IOException | DocumentException e) {
            e.printStackTrace();
        } finally {
            if (document != null) {
                document.close();
            }
        }
    }

    protected Paragraph addFont(String content) {
//        LimsRuleConfigBean ruleConfig = ruleConfigService.getRuleConfig(new RestJsonWrapperBean(){{setParamValue("type","页码颜色");}});
        BaseFont baseFont = null;
        try {
            try {
                ApplicationHome applicationHome = new ApplicationHome();
                File file = new File(applicationHome.getDir(), "/arial unicode ms.ttf");
                //file.getAbsolutePath()
                //baseFont=BaseFont.createFont("C:/Users/悟/Desktop/simsun_ttc/simsun.ttc,0",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);//D:/z/simsun.ttc,0是所下字体的路径
                baseFont = BaseFont.createFont(file.getAbsolutePath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);//D:/z/simsun.ttc,0是所下字体的路径
            } catch (DocumentException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        Font font = null;
        String RGB = "0,0,0";
        BaseColor color = null;
        String[] split = RGB.split(",");
        if (split.length > 2) {
            color = new BaseColor(Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2]));
        }

//        if("1".equalsIgnoreCase(ruleConfig.getExt$Item("flag")) && ruleConfig.getParamVal() != null) {
//            String[] split = ruleConfig.getParamVal().split(",");
//            if(split.length > 2) {
//                color = new BaseColor(Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2]));
//            }
//        }
        font = new Font(baseFont, 12f, Font.NORMAL, color);//设置字体
        return addText(content, font);
    }

    private static Paragraph addText(String content, Font font) {
        Paragraph paragraph = new Paragraph(content, font);
        paragraph.setAlignment(Element.ALIGN_LEFT);
        return paragraph;
    }
}
